package Multithread.Thread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 2 线程调度（启动、睡眠、优先级、终止）
 * 2.1 start/run 的区别（启动）
 * 2.2 sleep/yield 的区别（睡眠）
 * 2.3 setPriority 调整线程优先级
 * 2.4 join()等待线程结束
 * 2.5 interrupt()打断线程睡眠（sleep，wait，join、park）
 * 2.6 park()两阶段终止
 */
public class Thread02 {

    public static void main(String[] args) throws InterruptedException {

//        1.start/run 的区别
//        funThread01("run");
//        funThread01("start");

//        2.sleep/yield 的区别
//        funThread021();
//        funThread022();

//        3.setPriority：调整线程优先级
//        funThread03();

//        4.join()等待线程结束
//        funThread04();

//        5.interrupt()打断线程睡眠（sleep，wait，join）
//        funThread05();
    }

    /**
     * 1.start/run 的区别
     */
    public static void funThread01(String order){
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                System.out.println("this is funThread01");
                //在这里获取线程名称并输出可以观测到当前在哪个线程
                System.out.println("当前运行的线程是 ： "+Thread.currentThread().getName());
            }
        };
        if (order.equals("run")){
//            直接调用 run 是在主线程中执行了 run，没有启动新的线程
            t1.run();
        } else {
//            使用 start 是启动新的线程，通过新的线程间接执行 run 中的代码
            t1.start();
        }
    }

    /**
     * 2.sleep/yield 的区别 (sleep)
     * 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态（阻塞）
     * 其它线程可以使用 interrupt 方法打断正在睡眠的线程，这时 sleep 方法会抛出 InterruptedException
     * 睡眠结束后的线程未必会立刻得到执行
     * 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
     * 使用sleep方法，可以防止程序空转导致一直占用CPU资源至100%
     */
    public static void funThread021() throws InterruptedException {
        System.out.println("this is funThread02");

        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                int b=0;
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    System.out.println("this is funThread02 error");
                    e.printStackTrace();
                }
                System.out.println(++b);
            }
        };
        t1.start();
        System.out.println("funThread02: t1 is interrupt");

//        Thread.sleep(1000);
//        与Thread.sleep(1000)效果一样，只是可读性更好
        TimeUnit.SECONDS.sleep(1);

//        强制唤醒线程
        t1.interrupt();
    }

    /**
     * 2.sleep/yield 的区别 (yield)
     * 调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态，然后调度执行其它线程
     * 具体的实现依赖于操作系统的任务调度器
     * yield只是让出线程，而且没有等待时间
     */
    public static void funThread022(){
        System.out.println("this is funThread03");
        Runnable task1 = () -> {
            int count = 0;
            while (true){
                Thread.yield();
                System.out.println(" ---->2 " + count++);
            }
        };
        Thread t1 = new Thread(task1, "t1");
        t1.start();
    }

    /**
     * 3.setPriority() 调整线程优先级
     * 线程优先级会提示（hint）调度器优先调度该线程，但它仅仅是一个提示，调度器可以忽略它
     * 如果 cpu 比较忙，那么优先级高的线程会获得更多的时间片，但 cpu 闲时，优先级几乎没作用
     */
    public static void funThread03(){
        System.out.println("this is funThread04");
        Runnable task1 = () -> {
            int count = 0;
            for (;;) {
                Thread.yield();
                System.out.println("---->1 " + count++);
            }
        };
        Runnable task2 = () -> {
            int count = 0;
            for (;;) {
                System.out.println("\t\t---->2 " + count++);
            }
        };

        Thread t1 = new Thread(task1, "t1");
        Thread t2 = new Thread(task2, "t2");

//        setPriority()调整线程优先级
        t1.setPriority(Thread.MAX_PRIORITY);
        t2.setPriority(Thread.MIN_PRIORITY);

        t1.start();
        t2.start();

    }

    /**
     * 4.join()等待线程结束
     */
    public static void funThread04() throws InterruptedException {
        System.out.println("this is funThread05");
        AtomicInteger r = new AtomicInteger();
        Thread t1 = new Thread(() -> {
            System.out.println("new Thread 开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("new Thread 结束");
            r.set(10);
        });
        t1.start();

//        join：等待线程结束
//        t1.join();
//        join方法的底层是由wait方法实现
//        限时等待，只等待设定的时间
//        线程结束会导致join结束，不会死等至设定时间
//        如果不设置时间就是一直等回
//        t1.join(100);

        System.out.println("结果为:"+r);
        System.out.println("结束");
    }

    /**
     * 5.interrupt()打断线程睡眠（sleep，wait，join）
     */
    public static void funThread05() throws InterruptedException {

        System.out.println("this is funThread06");
        Thread t1 = new Thread( ()->{
            while (true){
                System.out.println("this is t1");
//                获取interrupted标志
                Boolean interrupted = Thread.currentThread().isInterrupted();
                System.out.println(interrupted);
//                终止线程
                if(interrupted){
                    System.out.println("t1 is interrupt");
                    break;
                }
            }
        },"t1");
        t1.start();

        Thread.sleep(1000);

        System.out.println("main is interrupt");
        System.out.println("interrupt会打断线程的睡眠，但不会打断线程执行，在线程方法内可以获取interrupted标识");
        t1.interrupt();
    }

}
